home *** CD-ROM | disk | FTP | other *** search
- // ear_calc.cp
- // This file contains functions that do number-crunching (plus
- // a few functions that do Unix-style I/O to files), but
- // nothing specific to the Mac.
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
-
- double sin(),cos(),sqrt(),fabs();
- #define PI 3.141592653589793
-
- #define NEED_MAC_STUFF 0
-
- #include "ear_prototypes.h"
- #include "ear_defines.h"
-
-
- /*
- Returns a random number in [0,1).
- */
- double
- random_double()
- {
- long int n1,n2;
- do {
- n1 = Random();
- }while(n1<-32766 || n1>32766);
- do {
- n2 = Random();
- }while(n2<-32766 || n2>32766);
- n1 += 32766;
- n2 += 32766; /* both in range of 0 to 65532 */
- n1 = n1 & 16383; /* avoid problems with sign */
- return (n1*65533L+n2)/1.073758204e+09;
- }
-
-
- /* Before calling the following, you must do:
- InitGraf(&thePort);
- or else use the stdio routines. */
- void
- init_random()
- {
- unsigned long t;
- int i,n;
- /* The following didn't work, same random numbers returned every time: */
- /*
- GetDateTime(&randSeed);
- */
-
- /* A total kludge: */
- GetDateTime(&t);
- n = 1 + (t & 1023L);
- for (i=1; i<=n; i++) {
- Random();
- }
- }
-
- /* generate a random number from 1 to n */
- int
- random_integer(int n)
- {
- int k;
- do {
- k = random_double()*n+1;
- } while (k<1 || k>n);
- return k;
- }
-
- double
- small_integer_ratio()
- {
- double x,y;
- x = small_integer();
- y = small_integer();
- return x/y;
- }
-
- int
- small_integer()
- {
- int n;
- n= 1;
- while (random_double()<.25) {
- ++n;
- }
- return n;
- }
- /*
- The main problem here is that we only have an 8-bit DAC, so we have to
- choose between distorting and making waveforms with amplitudes so small
- that you can hear the granularity. Waveforms are first normalized
- to have unit rms amplitude. Then they are transformed into 8-bit
- integers via
- 128+100*amplitude*waveform
- where amplitude is an input parameter, and results outside the range of 0-254
- result in clipping.
- Global variable wave_table_size should be set by calling routine, unless
- reading sample (kind=5).
- Amplitude should typically be set to about 0.3 to avoid distortion
- when summing the waveforms of four voices.
-
- modified 12 Mar 95 to renormalize just enough to avoid clipping
- */
- void
- make_wave_table(unsigned char *final_wave_table, //-- storage for final result
- double *temp_wave_table, //-- temporary storage
- int kind,
- double amplitude,
- int wave_table_size,
- int make_temp_wave_table)
- {
- int i,garbage;
- double x,s,max_value;
- static double raw_ampl,avg;
- if (make_temp_wave_table) {
-
- if (kind==5) {
- FILE *f;
- int z;
- char line[MAX_STR_LEN];
- f = fopen("wave_file","r");
- if (f==(FILE *)0) {
- bail_out("Error opening file for input\n");
- exit(-1);
- }
- wave_table_size = 0;
- fget_line(line,f);
- garbage = atoi(line); // pitch offset
- for (;;) {
- z = fget_line(line,f);
- if (z!=0) break;
- temp_wave_table[wave_table_size++] = atoi(line);
- }
- fclose(f);
- }
- else {
- for (i=0; i<wave_table_size; i++) {
- switch(kind) {
- /****** sine wave ******/
- case 1:
- x = ((double ) i)/((double) wave_table_size);
- s = sin(2.*PI*x);
- temp_wave_table[i] = s;
- break;
- /****** square wave ******/
- case 2:
- if (i<wave_table_size/2)
- temp_wave_table[i] = 1.0;
- else
- temp_wave_table[i] = -1.0;
- break;
- /****** square+sine wave ******/
- case 3:
- if (i<wave_table_size/2)
- temp_wave_table[i] = 0.5;
- else
- temp_wave_table[i] = -0.5;
- x = ((double ) i)/((double) wave_table_size);
- s = sin(2.*PI*x);
- temp_wave_table[i] += 0.5*s;
- break;
- /****** superimposed harmonics ******/
- case 4:
- {
- int nharm,j;
- double fall_off,f,u;
- nharm = 10;
- fall_off = 0.9;
- if (nharm>20) {
- bail_out("Error constructing waveform - too many harmonics\n");
- exit(-1);
- }
- x = ((double ) i)/((double) wave_table_size);
- temp_wave_table[i] = 0.0;
- u = 2.*PI*x;
- f = 1.0;
- for (j=1; j<=nharm; j++) {
- s = sin(u*j);
- temp_wave_table[i] += f*s;
- f = f*fall_off;
- }
- }
- break;
- } /* end case */
- } /* end for */
- } /* end else clause, i.e. not a sample */
- /* normalize: */
- raw_ampl = 0.0;
- avg = 0.0;
- for (i=0; i<wave_table_size; i++) {
- double u;
- u = temp_wave_table[i];
- avg += u;
- raw_ampl += u*u;
- }
- avg = avg/wave_table_size;
- raw_ampl = raw_ampl/wave_table_size;
- raw_ampl = sqrt(raw_ampl-avg*avg);
- max_value = 0.0;
- for (i=0; i<wave_table_size; i++) {
- if (fabs(temp_wave_table[i]-avg)>max_value)
- max_value = fabs(temp_wave_table[i]-avg);
- }
- if (amplitude*100*max_value/raw_ampl > 120.)
- raw_ampl = raw_ampl * (amplitude*100*max_value/raw_ampl/120.);
-
- }//-- end if make_temp_wave_table
-
- for (i=0; i<wave_table_size; i++) {
- double u;
- u = 128 + amplitude * 100 * (temp_wave_table[i]-avg) / raw_ampl;
- if (u>=254) u=254;
- if (u<=0) u = 0;
- final_wave_table[i] = u;
- }
- }
-
- int
- fget_line(char *line,FILE *f)
- {
- char *ret_val;
- ret_val = fgets(line,MAX_STR_LEN-5,f);
- if (ret_val==(char *) 0 || strlen(line)>MAX_STR_LEN-7) {
- *line = '\0';
- if (strlen(line)>MAX_STR_LEN-7)
- fprintf(stderr,"*** error - line too long\n");
- return 1;
- }
- if (line[strlen(line)-1]=='\n')
- line[strlen(line)-1] = '\0';
- return 0;
- }
-
- void
- debug_print(char *message)
- {
- FILE *f;
- static int created_file_already = 0;
- if (!created_file_already)
- f = fopen("errors","w");
- else
- f = fopen("errors","a");
- if (f != (FILE *) 0) {
- fprintf(f,"%s",message);
- fflush(f);
- fclose(f);
- created_file_already = 1;
- }
- }
-
- double
- choose_duration(double typical_tempo)
- {
- double min_duration,tempo,d;
- min_duration = .7 * 2000.*60./typical_tempo;
- tempo = typical_tempo*(1.+.2*(random_double()+random_double()-1.));
- d = 2000.*60./tempo;
- while (d<min_duration) {
- d *= 2;
- }
- return d;
- }
-
-